home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c)Copyright 1992-1997 Obvious Implementations Corp. Redistribution and
- * use is allowed under the terms of the DICE-LICENSE FILE,
- * DICE-LICENSE.TXT.
- */
-
- /*
- * TOPLEVEL.C
- */
-
- /*
- ** $Filename: toplevel.c $
- ** $Author: dice $
- ** $Revision: 30.326 $
- ** $Date: 1995/12/24 06:09:50 $
- ** $Log: toplevel.c,v $
- * Revision 30.326 1995/12/24 06:09:50 dice
- * .
- *
- * Revision 30.325 1995/12/24 05:38:17 dice
- * .
- *
- * Revision 30.6 1994/08/04 04:49:46 dice
- * fixed regargs bug. A previous fix involving automatic registerized
- * arguments broke explicit registerization of arguments when more then
- * four arguments are specified.
- *
- * Revision 30.0 1994/06/10 18:04:58 dice
- * .
- *
- * Revision 1.14 1993/11/22 00:28:36 jtoebes
- * Final cleanup to eliminate all cerror() messages with strings.
- *
- * Revision 1.14 1993/11/22 00:28:36 jtoebes
- * Final cleanup to eliminate all cerror() messages with strings.
- *
- * Revision 1.13 1993/09/18 21:03:26 jtoebes
- * Minor fix encountered when recursively recompiling compiler. Previous
- * fix failed to set the auto bit under some circumstances for local function
- * pointers.
- *
- * Revision 1.12 1993/09/13 21:28:23 jtoebes
- * Fixed BUG00117 - Problems with typdef'd functions.
- * Made error logic ignore function pointers declared in a local procedure.
- *
- * Revision 1.11 1993/09/11 23:25:16 jtoebes
- * Fixed BUG00047 - DC1 failes to warn about missing , in initialized expression.
- * Changed to conform to new calling parameters for CompBracedAssign.
- *
- * Revision 1.10 1993/09/06 23:37:12 jtoebes
- * Fixed BUG00102 - Constant expressions not allowed for bitfields.
- *
- * Revision 1.9 1993/09/06 14:10:15 jtoebes
- * fixed BUG00113 - const keyword was not allowed after the type.
- * Simply inserted parsing code for immediately after the type.
- *
- * Revision 1.8 1993/09/06 13:21:34 jtoebes
- * Fixed BUG01091 - Bad error for undefined structure tag.
- * Added code for arrays to ensure that structures and unions are defined
- * before attempting to make an array out of them.
- *
- * Revision 1.7 1993/09/06 11:06:50 jtoebes
- * Fixed BUG06063 - Error for initialization of an external array of chars.
- * Turned off extern bit when something was initialized.
- *
- * Revision 1.6 1993/09/05 23:54:32 jtoebes
- * Fixed BUG06045 - Enforcer hit for invalid structure definitions.
- * Added code to skip over current level of nesting when too many
- * initializers are given for a structure.
- *
- **/
-
- #include "defs.h"
-
-
- #define MAXCPX 64 /* maximum type declarator complexity */
-
- static short StructLevel; /* sp CompVar() does not call SemanticAdd() */
- static ExtVarNode *ExtBase;
- static ExtStrNode *StrBase;
-
- Prototype short TopLevel(short);
- Prototype short CompDecl(short, Var **, long);
- Prototype short CompType(short, Type **, long *, long *);
- Prototype short CompVar(short, Type *, long, long, Var **);
- Prototype short CompTypeDeclarators(short, Type **, Symbol **, long);
- Prototype short CompStructType(short, Type **, long);
- Prototype short CompEnumType(short, Type **);
- Prototype short CompTypeofType(short, Type **);
- Prototype short ResolveStructUnionType(Type *);
-
- Prototype void AddExternList(Var *);
- Prototype void DumpExternList(long);
- Prototype void AddStrList(ubyte *, long, long, long);
- Prototype void MakeStringConst(long);
- Prototype void DelStrList(long);
- Prototype void DumpStrList(void);
-
- Local short PointerOpt(Type **, Symbol **, short);
- Local short DirectDeclarator(Type **, Symbol **, short, long);
- Local void ReverseFeed(Type **, Type *);
- Local int ExplicitRegistersDeclared(Var **vars, long args);
-
-
- /*
- * TopLevel() expects:
- *
- * <decl>
- * typedef <decl>
- */
-
- short
- TopLevel(short t)
- {
- Var *var;
- Var *nv;
-
- /*
- * Do not absort the semicolon at the end of the statement as this
- * would require another lexical token causing a #pragma DCCOPTS
- * after a procedure definition to be interpreted before the previous
- * procedure's code was generated.
- */
-
- t = CompDecl(t, &var, 0);
-
- while (var) {
- nv = var->Next;
- GenerateVar(var);
- var = nv;
- }
-
- /*
- * Clear out any lingering expression structures here ??
- * Clear out all procedural sub-variables EXCEPT arguments to
- * the procedure and the procedure var itself. ??
- */
-
- t = GetToken();
-
- return(t);
- }
-
- short
- CompDecl(short t, Var **pvar, long absorbSemi)
- {
- short typeDef = 0; /* preceeded by typedef */
- Var *var = NULL;
- Type *baseType;
- long baseFlags;
- long regFlags;
- long li = LFBase->lf_Index;
-
- if (t == TokTypeDef) { /* opt typedef */
- t = GetToken();
- typeDef = 1;
- }
-
- /*
- * type spec
- */
-
- t = CompType(t, &baseType, &baseFlags, ®Flags);
-
- /*
- * list of type-qualfied variables (i.e. char *foo, the '*foo'). CompVar()
- * also parses entire subroutines and returns a pseudo ';' for them.
- *
- * The variables are semantically added
- */
-
- if (typeDef) {
- t = CompVar(t, baseType, baseFlags, regFlags, NULL);
- while (t == TokComma) {
- t = GetToken();
- t = CompVar(t, baseType, baseFlags, regFlags, NULL);
- }
- } else if (t != TokSemi) {
- Var *vlast;
- Var *v;
-
- t = CompVar(t, baseType, baseFlags, regFlags, &var);
- vlast = var;
-
- /*
- * Handle case where we compiled a procedure, the lexical index
- * must indicate the beginning of the procedure so debugging
- * info is aligned properly
- */
-
- if (var->Type->Id == TID_PROC)
- var->LexIdx = li;
-
- /*
- * Handle list of vars
- */
-
- while (t == TokComma) {
- t = GetToken();
- t = CompVar(t, baseType, baseFlags, regFlags, &v);
-
- vlast->Next = v;
- vlast = v;
- }
- vlast->Next = NULL;
- }
- if (t != TokSemi) {
- zerror(EWARN_EXPECTED_SEMICOLON);
- if (LFBase->lf_Index == li)
- t = GetToken();
- }
-
- if (absorbSemi)
- t = GetToken();
-
- *pvar = var;
- return(t);
- }
-
- short
- CompType(short t, Type **ptype, long *pflags, long *rflags)
- {
- Type *type;
- long flags = 0;
-
- *rflags = 0;
-
- /*
- * Allow register qualifiers before or after type qualifiers for
- * SAS/C compatibility. Personally, DICE likes them before
- */
-
- while (t == TokTypeQual) {
- flags |= (long)LexData;
- t = GetToken();
- }
- while (t == TokRegQual) {
- if (*rflags)
- zerror(EERROR_ILLEGAL_REGSPEC);
- else
- *rflags = (long)LexData | RF_REGISTER;
- t = GetToken();
- }
- while (t == TokTypeQual) {
- flags |= (long)LexData;
- t = GetToken();
- }
- if (t == TokTypeId) {
- type = (Type *)LexData;
- t = GetToken();
- while (t == TokTypeQual) {
- flags |= (long)LexData;
- t = GetToken();
- }
- if (t == TokTypeId) {
- if ((Type *)LexData == &LongType && (type == &ShortType || type == &LongType)) {
- t = GetToken();
- } else if ((Type *)LexData == &DoubleType && type == &LongType) {
- type = &LongDoubleType;
- t = GetToken();
- }
- /* note, can't else error since structure elements may
- * be type names
- */
- }
- } else if (t == TokStruct || t == TokUnion) {
- t = CompStructType(t, &type, flags);
- } else if (t == TokEnum) {
- t = CompEnumType(t, &type);
- } else if (t == TokTypeof) {
- t = CompTypeofType(t, &type);
- } else {
- type = &LongType;
- }
-
- flags |= type->Flags;
-
- while (t == TokTypeQual && ((long)LexData & TF_STORQUALMASK)) {
- /*
- * Generate warning, but accept type. Note that the qualifier
- * will apply to ALL declarations in this statement rather then
- * just the first as in SAS/C, thus the warning.
- */
- zerror(EWARN_SASC_QUALIFIER_PLACEMENT);
- flags |= (long)LexData;
- t = GetToken();
- }
-
- if ((type->Flags & TF_TYPEQUALMASK) != (flags & TF_TYPEQUALMASK))
- type = TypeToQualdType(type, flags & TF_TYPEQUALMASK);
-
- *ptype = type;
- *pflags= flags & TF_STORQUALMASK;
-
- return(t);
- }
-
- /*
- * Compile a variable... handle *, [], (), etc... void (*ptr)()
- * also handle '= expression'
- * also handle bit fields though currently they are
- * NOT implemented properly.
- *
- * if pvar == NULL then we are compiling a typedef. Return TokSemi for
- * procedural declarations that end with '}'.
- *
- * baseType->Flags holds TYPEQUALMASK flags while
- * storFlags holds STORQUALMASK flags.
- */
-
- short
- CompVar(short t, Type *baseType, long storFlags, long regFlags, Var **pvar)
- {
- Var *var = NULL;
- Type *type;
- Symbol *sym = NULL;
- long extraTypeFlags = 0; /* propogated through override */
- short protoVoid = 0;
-
- /*
- * step 1, parse the name .. get the name symbol and representitive type
- */
-
- type = baseType;
-
- t = CompTypeDeclarators(t, &type, &sym, storFlags);
-
- if (type->Flags & TF_STKCALL) storFlags &= ~TF_REGCALL;
-
- if (t == TokColon) {
- long bits;
- Exp *exp = NULL;
-
- if (StructLevel == 0)
- zerror(EERROR_ILLEGAL_BITFIELD_OP);
-
- if (type->Id != TID_INT || (type->Size != 4 && type->Size != 2))
- zerror(EERROR_ILLEGAL_BITFIELD_OP);
-
- t = GetToken();
- t = CompExp(t, &exp, 0);
- bits = ExpToConstant(exp);
-
- if (bits > 32 || bits < 0) {
- zerror(EERROR_ILLEGAL_BITFIELD_OP);
- bits = 32;
- }
- type = MakeBitfieldType(type->Flags & TF_UNSIGNED, bits);
- }
-
- /*
- * Create final type that includes storage qualifiers.
- */
-
- if ((storFlags & TF_STORNOTLOCAL) == 0 && State != SOUTSIDE)
- {
- /* Check to see that this is a pointer to a function */
- if (type->Id != TID_PTR ||
- type->SubType == NULL ||
- type->SubType->Id != TID_PROC)
- {
- if (storFlags & TF_AUTOILLEGAL)
- zerror(EERROR_ILLEGAL_QUALIFIER);
- }
- storFlags |= TF_AUTO;
- }
-
- {
- long tflags = (type->Flags | storFlags) & ~TF_NOTINTYPE;
-
- if (type->Flags != tflags)
- type = TypeToQualdType(type, tflags);
- }
-
- /*
- * If typedef we stop here
- */
-
- if (pvar == NULL) {
- if (type->Flags != (type->Flags | storFlags))
- type = TypeToQualdType(type, type->Flags | storFlags);
-
- if (t != TokSemi && t != TokComma)
- zerror(EERROR_ILLEGAL_TYPEDEF);
- if (sym)
- SemanticAdd(sym, TokTypeId, type);
- else
- zerror(EERROR_ILLEGAL_TYPEDEF);
- return(t);
- }
-
- /*
- * definitely a variable. Check for overide of previous def
- * in this block level, or global block level if not auto.
- *
- * STATIC VARIABLES inside subroutines are special, they do not bother
- * global variables outside subroutines of the same name.
- *
- * check opt '= exp' and optional code if a procedure
- */
-
- if (sym == NULL)
- {
- /* Well, we have a syntax error */
- zerror(EERROR_SYNTAX_ERROR_DECL);
- sym = MakeSymbol("<PHONEYSYM>", 11, LFBase->lf_Index, NULL);
- storFlags |= VF_DECLD;
- }
-
- if (StructLevel == 0 && (var = BlockRemoveDuplicateVar(storFlags, sym, type))) {
- extraTypeFlags = (var->Type->Flags | storFlags) & TF_KEEPPROC;
- if (var->Type->Args == 0) /* proto was ... foo(void) */
- protoVoid = 1;
-
- if ((type->Flags & TF_KEEPPROC) != (extraTypeFlags & TF_KEEPPROC))
- type = TypeToQualdType(type, type->Flags | extraTypeFlags);
- }
-
- if (var == NULL) {
- if (StructLevel == 0 && State != SOUTSIDE && (storFlags & TF_STORNOTLOCAL) == 0 && type->Id != TID_PROC) {
- var = AllocTmpStructure(Var); /* does not survive subroutine */
- } else {
- var = AllocStructure(Var); /* permanent */
- }
- if (sym && StructLevel == 0) {
- if (type->Id == TID_PROC || (storFlags & TF_EXTERN))
- SemanticAddTop(sym, TokVarId, var);
- else
- SemanticAdd(sym, TokVarId, var);
- }
- }
-
- var->Type = type;
- var->Sym = sym;
- var->LexIdx = LFBase->lf_Index;
-
- if (storFlags & TF_REGISTER)
- ++var->Refs;
-
- if ((type->Id == TID_STRUCT || type->Id == TID_UNION) && (type->Size == 0))
- {
- Undefined_Tag(type, sym, LFBase->lf_Index);
- }
-
- *pvar = var;
-
- if (State == SOUTSIDE && (storFlags & TF_AUTO))
- zerror(EERROR_ILLEGAL_QUALIFIER);
-
- var->Flags = type->Flags | storFlags | extraTypeFlags | (var->Flags & VF_DECLD);
- var->RegFlags = regFlags;
-
- #ifdef DYNAMIC
- if ((var->Flags & (TF_EXTERN|TF_DYNAMIC)) == TF_DYNAMIC) {
- var->Type = type = TypeToPtrType(var->Type);
- asm_dynamictag(var);
- }
- #endif
- if (type->Id == TID_PROC) {
- if (t != TokSemi && t != TokComma) { /* definition */
- var->Flags &= ~(VF_DECLD | TF_EXTERN);
-
- /*
- * if not a prototyped procedure must munge arguments properly.
- * This applies to floats, for example, which are really doubles
- * for non-prototyped procedures.
- */
-
- if ((type->Flags & TF_PROTOTYPE) == 0) {
- short i;
- for (i = 0; i < type->Args; ++i) {
- Type **t2 = &type->Vars[i]->Type;
- *t2 = ActualArgType(*t2);
- }
- }
-
- /*
- * munge routine prototyped as foo(void) but declared foo()
- */
-
- if (protoVoid && type->Args < 0)
- var->Type = type = TypeToProcType(type->SubType, NULL, 0, type->Flags | TF_PROTOTYPE);
-
- if (var->u.Block && !(var->Flags & TF_STATIC))
- zerror(EERROR_MULTIPLY_DEFINED_PROC);
-
- t = CompProcedure(t, var);
-
- } else {
- if (var->u.Block == NULL) {
- if (!(var->Flags & TF_STATIC))
- var->Flags |= TF_EXTERN;
- } else {
- zerror(EERROR_MULTIPLY_DEFINED_PROC);
- }
-
- /*
- * Generate Register Specification Output Data
- */
-
- if (RegSpecOutputOpt)
- GenerateRegSpecOutput(var);
- }
- } else {
- if (t == TokEq) { /* assigned expression */
- Exp *exp;
-
- /* Any assignment to a global variable will eliminate the extern */
- /* portion of the symbol. This is in accordance to ANSI. */
- var->Flags &= ~TF_EXTERN;
-
- if (StructLevel)
- zerror(EERROR_ILLEGAL_ASSIGNMENT);
-
- t = GetToken();
- if (t == TokLBrace)
- {
- t = CompBracedAssign(GetToken(), var->Type, &exp, 1, sym);
- if (t != TokRBrace)
- {
- zerror(EERROR_TOO_MANY_INITIALIZERS);
- t = match_nesting(t);
- }
- t = GetToken();
- }
- else if (t == TokStrConst && var->Type->Id == TID_ARY)
- {
- t = CompBracedAssign(t, var->Type, &exp, 0, sym);
- }
- else if ((var->Flags & TF_AUTO) == 0)
- {
- t = CompBracedAssign(t, var->Type, &exp, 0, sym);
- } else
- {
- /* If we get here, we know that the TF_AUTO bit is on. If */
- /* the TF_STATIC flag is also set, this should be diagnosed */
- /* This logic used to be in the previous test, but since it */
- /* really can never occur, we moved it down here and expect */
- /* to take it out after the beta. */
- /* Note that the assignment code will be pulled out by the */
- /* block code in stmt.c (only simple assignments) */
- if (var->Flags & TF_STATIC)
- {
- dbprintf(("Unexpected Type %ld\n", var->Flags));
- Assert(0);
- }
- t = CompExp(t, &exp, 0);
- }
- var->u.AssExp = exp;
- }
- }
- return(t);
- }
-
- /*
- * abstract:
- * PTR
- * PTRopt direct
- *
- * direct:
- * (abstract)
- * DIRECTopt [constant-exp]
- * DIRECTopt (parameter-type-list)
- *
- * storFlags might apply to some lower level type (procedure spec)
- */
-
- short
- CompTypeDeclarators(short t, Type **ptype, Symbol **psym, long storFlags)
- {
- Type *head = NULL;
-
- /* *ptype = baseType; */
-
- if (t == TokStar)
- t = PointerOpt(ptype, psym, t);
-
- switch(t) {
- case TokLParen: /* late eval */
- head = &CharType;
- t = CompTypeDeclarators(GetToken(), &head, psym, 0);
- t = SkipToken(t, TokRParen);
- break;
- case TokVarId: /* symbol */
- case TokId:
- case TokTypeId:
- case TokEnumConst:
- *psym = LexSym;
- t = GetToken();
- break;
- /* default: break; */ /* other */
- }
-
- t = DirectDeclarator(ptype, psym, t, storFlags);
-
- /*
- * Stick head in front of ptype. Must scan head in reverse.
- */
-
- if (head)
- ReverseFeed(ptype, head);
-
- return(t);
- }
-
- void
- ReverseFeed(ptype, type)
- Type **ptype;
- Type *type;
- {
- if (type) {
- ReverseFeed(ptype, type->SubType);
-
- switch(type->Id) {
- case TID_INT:
- break; /* done */
- case TID_PTR:
- *ptype = TypeToPtrType(*ptype);
- break;
- case TID_ARY:
- {
- long entries = 0;
-
- if (type->SubType->Size)
- entries = type->Size / type->SubType->Size;
- *ptype = TypeToAryType(*ptype, NULL, entries);
- }
- break;
- case TID_PROC:
- *ptype = TypeToProcType(*ptype, type->Vars, type->Args, type->Flags);
- break;
- default:
- dbprintf(("typedecl/tid %d\n", type->Id));
- Assert(0);
- break;
- }
- }
- }
-
- short
- PointerOpt(Type **ptype, Symbol **psym, short t)
- {
- while (t == TokStar) {
- long flags = 0;
-
- t = GetToken();
- *ptype = TypeToPtrType(*ptype);
- while (t == TokTypeQual) {
- flags |= (long)LexData;
- t = GetToken();
- }
- if (flags) {
- Type *type = *ptype;
- *ptype = TypeToQualdType(type, (flags | type->Flags) & TF_TYPEQUALMASK);
- }
- }
- return(t);
- }
-
- short
- DirectDeclarator(Type **ptype, Symbol **psym, short t, long storFlags)
- {
- switch(t) {
- case TokLParen:
- {
- Var **vars;
- long args;
- long flags;
- t = CompProcedureArgDeclarators(GetToken(), &vars, &args, &flags);
-
- t = DirectDeclarator(ptype, psym, t, 0);
-
- /*
- * Finish up. If procedure is not already registerized determine
- * whether to make it so or not. (flags & TF_STKCALL) is set when
- * automatic registerization is not possible, (storFlags & TF_STKCALL)
- * when the user explicitly does not want automatic registerization
- *
- * If explicit registers have been declared, do NOT set
- * TF_STKCALL.
- */
-
- if (args <= 0 || args > 4) {
- if (ExplicitRegistersDeclared(vars, args) == 0)
- flags |= TF_STKCALL;
- }
- if ((flags & TF_REGCALL) == 0)
- {
- if (((storFlags|flags) & TF_STKCALL) == 0 &&
- (RegCallOpt || (storFlags & TF_REGCALL)) && !(flags & TF_DOTDOTDOT)
- && args > 0 && args <= 4)
- flags |= TF_REGCALL;
- }
- storFlags &= ~TF_REGCALL;
-
- if (flags & TF_REGCALL)
- AutoAssignRegisteredArgs(vars, args);
- *ptype = TypeToProcType(*ptype, vars, args, flags | storFlags);
- }
- break;
- case TokLBracket:
- {
- Exp *exp = NULL;
-
- t = GetToken();
- if (t != TokRBracket)
- t = CompExp(t, &exp, 1);
-
- if (((*ptype)->Id == TID_STRUCT || (*ptype)->Id == TID_UNION) && ((*ptype)->Size == 0))
- {
- Undefined_Tag(*ptype, NULL, LFBase->lf_Index);
- }
-
- t = SkipToken(t, TokRBracket);
-
- t = DirectDeclarator(ptype, psym, t, storFlags);
-
- if ((*ptype)->Size == 0) {
- zerror(EERROR_SIZEOF_TYPE_0);
- }
- *ptype = TypeToAryType(*ptype, exp, 0);
- }
- break;
- default: /* fix the ordering */
- break;
- }
- return(t);
- }
-
- /*
- * Scan procedure variables to determine if explicit
- * registers have been declared.
- */
-
- int
- ExplicitRegistersDeclared(Var **vars, long args)
- {
- long i;
- int r = 0;
-
- for (i = 0; i < args; ++i, ++vars) {
- if ((*vars)->RegFlags & RF_REGISTER) {
- r = 1;
- break;
- }
- }
- return(r);
- }
-
- /*
- * Access/compile a structural type that may or may not exist yet.
- *
- * t == TokStruct or TokUnion. s/u [optid] [{ structure}]
- */
-
- short
- CompStructType(short t, Type **ptype, long flags)
- {
- short isUnion = (t == TokUnion);
- Type *type;
-
- t = GetToken();
- if (t == TokId || t == TokTypeId || t == TokVarId || t == TokEnumConst) {
- if ((type = FindStructUnionType(LexSym, isUnion)) == NULL)
- type = MakeStructUnionType(LexSym, isUnion);
- t = GetToken();
- } else {
- type = MakeStructUnionType(NULL, isUnion);
- }
-
- if (t == TokLBrace) {
- t = ResolveStructUnionType(type);
- }
-
- *ptype = type;
- return(t);
- }
-
- short
- ResolveStructUnionType(type)
- Type *type;
- {
- short t;
-
- {
- Var **vars = NULL;
- Var *var;
- short n = 0;
- short siz = 0;
-
- t = GetToken();
- ++StructLevel;
- while (t && t != TokRBrace) {
- t = CompDecl(t, &var, 1);
- while (var) {
- if (n == siz) {
- siz += 4;
- vars = zrealloc(vars, sizeof(Var *), n, siz);
- }
- vars[n++] = var;
- var = var->Next;
- }
- }
- --StructLevel;
- if (siz == 0)
- {
- zerror(EERROR_NO_MEMBERS, SymToString(FindStructUnionTag(type)));
- vars = zrealloc(vars, sizeof(Var *), 1, 1);
- var = AllocStructure(Var);
- var->Type = &LongType;
- vars[0] = var;
- n = 1;
- }
-
- SetStructUnionType(type, vars, n, type->Flags);
- if (t == TokRBrace)
- t = GetToken();
- }
- return(t);
- }
-
- /*
- * Access/compile an enum type that may or may not exist yet.
- *
- * enum [enumName] [{ specifiers }]
- */
-
- short
- CompEnumType(short t, Type **ptype)
- {
- Type *type;
-
- t = GetToken();
- if (t == TokId || t == TokTypeId || t == TokVarId || t == TokEnumConst) {
- if ((type = FindEnumType(LexSym)) == NULL)
- type = MakeEnumType(LexSym);
- t = GetToken();
- } else {
- type = MakeEnumType(NULL);
- }
- if (t == TokLBrace) {
- long eval = 0;
- t = GetToken();
- while (t != TokRBrace) {
- Symbol *sym;
- if (t != TokId) {
- if (t == TokVarId || t == TokTypeId) {
- zerror(EWARN_ENUM_OVERIDE);
- } else {
- zerror(EERROR_SYNTAX_ERROR_DECL);
- break;
- }
- }
- sym = LexSym;
- t = GetToken();
- if (t == TokEq) {
- Exp *exp;
-
- t = GetToken();
- t = CompExp(t, &exp, 0);
- eval = ExpToConstant(exp);
- }
- AddEnumIdent(type, sym, eval);
- ++eval;
- if (t == TokComma) {
- t = GetToken();
- } else if (t != TokRBrace) {
- zerror(EERROR_SYNTAX_ERROR_DECL);
- break;
- }
- }
- if (t == TokRBrace)
- t = GetToken();
- }
- *ptype = type;
- return(t);
- }
-
- /*
- * Compile typeof(exp)
- */
-
- short
- CompTypeofType(short t, Type **ptype)
- {
- Exp *exp;
-
- t = SkipToken(GetToken(), TokLParen);
- t = CompExp(t, &exp, 1);
- t = SkipToken(t, TokRParen);
- *ptype = ExpToType(exp);
- return(t);
- }
-
- void
- AddExternList(var)
- Var *var;
- {
- ExtVarNode *evn = AllocStructure(ExtVarNode);
-
- evn->Next = ExtBase;
- evn->Var = var;
- ExtBase = evn;
- }
-
- void
- DumpExternList(long procs)
- {
- ExtVarNode *evn;
- Var *var;
-
- for (evn = ExtBase; evn; evn = evn->Next) {
- var = evn->Var;
- if ((procs && var->Type->Id == TID_PROC) || (!procs && var->Type->Id != TID_PROC)) {
- if ((var->Flags & TF_EXTERN) && (var->Flags & VF_DECLD) && !(var->Flags & VF_EXTD))
- asm_extern(var);
- if (var->Flags & VF_DECLD)
- var->Flags |= VF_EXTD;
- }
- }
- }
-
- void
- AddStrList(name, len, label, iidx)
- ubyte *name;
- long len;
- long label;
- long iidx;
- {
- ExtStrNode *esn = AllocStructure(ExtStrNode);
-
- esn->Next = StrBase;
- esn->Str = name;
- esn->Len = len;
- esn->Label = label;
- esn->IIdx = iidx;
-
- /*
- * Internationalizable strings are always constant so we can have a
- * relocation reference and still support residentable code.
- */
-
- if (ConstCode || (iidx >= 0))
- esn->Flags = TF_CONST;
- else
- esn->Flags = 0;
- StrBase = esn;
- }
-
- void
- DelStrList(label)
- long label;
- {
- ExtStrNode **ep;
-
- for (ep = &StrBase; *ep && (*ep)->Label != label; ep = &(*ep)->Next);
- if (*ep)
- *ep = (*ep)->Next;
- }
-
- void
- DumpStrList()
- {
- ExtStrNode *esn;
-
- for (esn = StrBase; esn; esn = esn->Next)
- asm_string(esn->Label, esn->Str, esn->Len, esn->Flags, esn->IIdx);
- }
-